'''
Created on 2011-03-04

@author: user1
'''
import time
import binascii
class gtp_packet:
    IMSI='02'
    RECOVERY='0e'
   
    def __init__(self,flags,msg_type,h_teid,seq,n_pdu,next_ext_head,imsi,recovery,my_ip):
        self.ver='1'
        self.flags='32'
        self.msg_type=msg_type
        self.n_pdu=n_pdu
        self.next_ext_head=next_ext_head
        self.imsi="1000000"
        self.h_teid=h_teid
        self.seq=seq
        self.nsapi="1"
        self.selection_mode='0f01'
        
        self.qos_v1='87000401020304'
        self.isdn='860007916407113254f6'
        self.recovery='0e2d'
        self.end_user_addr='800002f121'
        self.apn='83000d0c696e7465726e65742e6f7267'
        self.teid_d=1
        self.teid_c=6553
        self.apn_rest='95000101'
        self.rat_type='97000101'
        #self.user_loc_info='9800080013005112121111'
        self.imei='9a00080101010101010101'
        self.sgsn_c='850004'+self.DecToHex(my_ip)
        self.sgsn_d='850004'+self.DecToHex(my_ip)
       
        #v0
        self.routing_area_identity='0322f601fffeff'
        self.h_flow_label='0000'
        self.tid=23456
        self.sndcp='ffffffff'
        self.qos_v0='061b921f'

        #v2
        self.mme_ip=my_ip
        self.pgw_ip=my_ip
        self.spare='00'
        self.msisdn_v2='4c00070021436587090010'
        self.mei_v2='4b0008003a95110600000000'
        self.uli='56000d0018223233000122323300000001'
        self.serving_net='53000300223233'
        self.rat_type_v2='5200010006'
        self.indication='4d0002000000'
        self.selection_mode_v2='80000100fc'
        self.pdn_type='6300010001'
        self.pdn_address_allocation='4f000500010b000132'
        self.apn_restriction_v2='7f00010000'
        self.ambr_v2='480008000000019000000190'
        self.grouped_ie='5d001f00490001000550001600046f0000000000000000000000000000000000000000'

             
    def DecToHex(self,dec_ip):
        dec_octets = str.split(dec_ip, '.')
        hex_octets = []

        if len(dec_octets) != 4:
            return "address error"
        for dec_octet in dec_octets:
            if int(dec_octet) > 255:
                return "address error"

            if int(dec_octet) < 16:
                hex_octets.append('0' + hex(int(dec_octet))[2:])
            else:
                hex_octets.append(hex(int(dec_octet))[2:])
            print "hex_octets is ",hex_octets

        #hex_octets.insert(2, ':')
        hex_ip = ''.join(hex_octets)
        return hex_ip

    def set_flags_by_ver(self,ver):
        if ver=='1' :
           self.flags='32'
        elif ver=='0' :
           self.flags='1e'
        elif ver=='2' :
           self.flags='48'
        return self.flags
    def teid_d(self,channel_data):
        self.channel_data=channel_data
    def pdp_echo_req(self):
        seq_encode=hex(self.seq)[2:].zfill(4)
        self.msg_type='01'
        content=seq_encode+self.n_pdu+self.next_ext_head
        self.length=hex(len(content)/2)[2:].zfill(4)
        data=self.flags+self.msg_type+self.length+self.h_teid+content
        return data
    def imsi_convert(self,imsi_ori):
	i=0
	length=len(imsi_ori)
        if length%2 == 1: 
		imsi_ori="0"+imsi_ori
                length=length+1
	imsi_new=""
	while i<length :
	        b=imsi_ori[i+1]+imsi_ori[i]
	        imsi_new=imsi_new+b
	        i=i+2
	return imsi_new
    def create_pdp_req(self):
        self.flags=self.set_flags_by_ver(self.ver)
        nsapi_encode='14'+hex(int(self.nsapi))[2:].zfill(2)
        print "nsapi_encode: ",self.nsapi,"->",nsapi_encode
        seq_encode=hex(self.seq)[2:].zfill(4)
        
	self.imsi=int(self.imsi)
        print "self.imsi: ",self.imsi
        imsi_new=self.imsi_convert(str(self.imsi))
        imsi_encode='02'+imsi_new.zfill(16)
        imsi_v2_encode='01000800'+imsi_new.zfill(16)
        print "imsi_encode: ",self.imsi,"->",imsi_encode
        self.imsi+=1
        
        teid_d_encode='10'+hex(self.teid_d)[2:].zfill(8)
        teid_c_encode='11'+hex(self.teid_c)[2:].zfill(8)
        flow_label_d_encode='10'+hex(self.teid_d)[2:].zfill(4)
        flow_label_c_encode='11'+hex(self.teid_c)[2:].zfill(4)
        print "flow_label_c is ",flow_label_c_encode
        print "flow_label_d is ",flow_label_d_encode
        self.teid_d+=1
        self.teid_c+=1

        #convert apn
        length=hex(len(self.apn))[2:].zfill(2)
        length_all=hex(len(self.apn)+1)[2:].zfill(4)
        apn_encode='83'+length_all+length+binascii.b2a_hex(self.apn)
        apn_v2_encode='47'+length_all+'00'+length+binascii.b2a_hex(self.apn)
        if self.ver == '1' :
            self.msg_type='10'
            #Donot understand why openggsn requires self.selection_mode
            content=seq_encode+self.n_pdu+self.next_ext_head+imsi_encode+self.recovery+self.selection_mode+teid_d_encode+ \
            teid_c_encode+nsapi_encode+self.end_user_addr+apn_encode+self.sgsn_c+self.sgsn_d+\
            self.isdn+self.qos_v1+self.apn_rest+self.rat_type+self.imei
            #self.isdn+self.qos+self.apn_rest+self.rat_type+self.user_loc_info+self.imei
            #print "content is:", content, " len is ", len(content)
            #print "hex len is ", hex(len(content)/2)
            self.length=hex(len(content)/2)[2:].zfill(4)
            print "h_teid is",self.h_teid
            data=self.flags+self.msg_type+self.length+self.h_teid+content
        elif self.ver == '0' :
            self.msg_type='10'
            self.tid_encode=str(self.tid).zfill(16)
            print "self.tid encode is ",self.tid_encode
            self.tid+=1
            #print "content is: ",content
            content=self.qos_v0+self.recovery+self.selection_mode+flow_label_d_encode+flow_label_c_encode+self.end_user_addr+apn_encode+self.sgsn_c+self.sgsn_d+self.isdn
            #content=self.routing_area_identity+self.qos+self.recovery+self.selection_mode+flow_label_d_encode+flow_label_c_encode+self.end_user_addr+apn_encode+self.sgsn_c+self.sgsn_d+self.isdn
            self.length=hex(len(content)/2)[2:].zfill(4)
            #data=self.flags+self.msg_type+self.length+seq_encode+self.h_flow_label+self.tid_encode+content
            data=self.flags+self.msg_type+self.length+seq_encode+self.h_flow_label+self.sndcp+self.tid_encode+content
            print "data is ",data
        elif self.ver == '2' :
            seq_encode=hex(self.seq)[2:].zfill(6)
            self.msg_type='20'
            mme_ip_encode=self.DecToHex(self.mme_ip)
            print "mme_ip_encode is:",self.mme_ip,"-->",mme_ip_encode
            pgw_ip_encode=self.DecToHex(self.pgw_ip)
            self.fteid_mme='570009008a'+hex(self.teid_c)[2:].zfill(8)+mme_ip_encode
            self.fteid_pgw='5700090187'+hex(self.teid_d)[2:].zfill(8)+pgw_ip_encode
            content=self.h_teid+seq_encode+self.spare+imsi_v2_encode+self.msisdn_v2+self.mei_v2+self.uli+ \
                    self.serving_net+self.rat_type_v2+self.indication+self.fteid_mme+self.fteid_pgw+apn_v2_encode+ \
                    self.selection_mode_v2+self.pdn_type+self.pdn_address_allocation+self.apn_restriction_v2+self.ambr_v2+self.grouped_ie
            self.length=hex(len(content)/2)[2:].zfill(4)
            data=self.flags+self.msg_type+self.length+content
        return data
    def update_pdp_req(self):
        self.msg_type='12'
        #convert apn
        length=hex(len(self.apn))[2:].zfill(4)
        nsapi_encode='14'+hex(int(self.nsapi))[2:].zfill(2)
        print "nsapi_encode: ",self.nsapi,"->",nsapi_encode
        seq_encode=hex(self.seq)[2:].zfill(4)
        
        imsi_encode='02'+hex(self.imsi)[2:].zfill(16)
        self.imsi+=1
        
        teid_d_encode='10'+hex(self.teid_d)[2:].zfill(8)
        teid_c_encode='11'+hex(self.teid_c)[2:].zfill(8)
        self.teid_d+=1
        self.teid_c+=1
        apn_encode='83'+length+binascii.b2a_hex(self.apn)
        #Donot understand why openggsn requires self.selection_mode
        content=seq_encode+self.n_pdu+self.next_ext_head+imsi_encode+self.recovery+self.selection_mode+teid_d_encode+ \
        teid_c_encode+nsapi_encode+self.end_user_addr+apn_encode+self.sgsn_c+self.sgsn_d+\
        self.isdn+self.qos_v1
        #print "content is:", content, " len is ", len(content)
        #print "hex len is ", hex(len(content)/2)
        self.length=hex(len(content)/2)[2:].zfill(4)
        print "h_teid is",self.h_teid
        data=self.flags+self.msg_type+self.length+self.h_teid+content
        return data
class gtp_custom :
    def __init__(self):
        self.action='send'
        self.type='pdp_context_req'
        self.attr={} 

class socks :
    def __init__(self):
        self.socket={}
        self.cur_step=1      

